package com.spark.lola.service.pur.impl;

import com.spark.lola.constant.SupOrderStatus;
import com.spark.lola.constant.SupReturnStatus;
import com.spark.lola.entity.pur.*;
import com.spark.lola.mapper.pur.OrderLocationMapper;
import com.spark.lola.mapper.pur.ReturnOrderInfoMapper;
import com.spark.lola.service.pur.IReturnOrderInfoService;
import com.spark.lola.service.pur.IReturnOrderProductService;
import com.spark.lola.support.common.entity.ShiroUser;
import com.spark.lola.support.common.util.DataBeanUtils;
import com.spark.lola.support.common.util.TimeUtil;
import com.spark.lola.support.mybatis.service.impl.BaseServiceImpl;
import com.spark.lola.support.wms.cache.CollectionCache;
import com.spark.lola.support.wms.constant.KafkaTopic;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.kafka.core.KafkaTemplate;
import org.springframework.stereotype.Service;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.stream.Stream;

/**
 * <p>
 *  服务实现类
 * </p>
 *
 * @author dengyejun
 * @since 2020-05-18
 */
@Service
public class ReturnOrderInfoServiceImpl extends BaseServiceImpl<ReturnOrderInfoMapper, ReturnOrderInfo> implements IReturnOrderInfoService {
    private static final Logger logger = LoggerFactory.getLogger(OrderInfoServiceImpl.class);

    @Autowired
    private OrderLocationMapper orderLocationMapper;

    @Autowired
    private IReturnOrderProductService returnOrderProductService;
    @Autowired
    private KafkaTemplate<String,String> kafkaTemplate;

    @Override
    public ReturnOrderInfo findFullById(Long orderId) {
        ReturnOrderInfo model = this.getById(orderId);
        List<ReturnOrderProduct> details = returnOrderProductService.getDetails(orderId);
        OrderLocation orderLocation = orderLocationMapper.selectByOrderId(0,model.getOrderId());
        model.setConsignee(CollectionCache.employees.get(model.getConsigneeId()));
        model.setDetails(details);
        model.setOrderLocation(orderLocation);
        return model;
    }

    @Override
    public Long add(OrderInfo form, ShiroUser shiroUser) throws Exception {
        logger.info("====创建退货单【{}】创建人【{}】===START===", form.getNo(), shiroUser.getLoginNo());
        ReturnOrderInfo model = new ReturnOrderInfo(form);
        List<ReturnOrderProduct> details =new ArrayList<>();
        form.getDetails().forEach(o->{
            ReturnOrderProduct detail =new ReturnOrderProduct(o);
            details.add(detail);
        });
        model.setDetails(details);
        logger.info("===处理订单明细...");
        dealProduct(model);
        logger.info("===保存退货单基础数据...");
        if (!this.save(model)) {
            throw new Exception("退货单保存失败");
        }
        logger.info("===保存货品明细...");
        model.getDetails().forEach(o -> o.setParentId(model.getId()));
        if (!returnOrderProductService.saveOrUpdateBatch(model.getDetails(), 100)) {
            throw new Exception("货品明细保存失败");
        }
        logger.info("====创建退货单【{}】创建人【{}】===END===", form.getNo(), shiroUser.getLoginNo());
        return  model.getId();
    }

    @Override
    public ReturnOrderInfo update(ReturnOrderInfo form, ShiroUser shiroUser) throws Exception {
        logger.info("====修改订单【{}】修改人【{}】===START===", form.getNo(), shiroUser.getLoginNo());
        ReturnOrderInfo model = this.findFullById(form.getId());
        if (model.getStatus().intValue() > SupOrderStatus.WAIT_PAYMENT) {
            throw new Exception("当前订单已生效，禁止修改");
        }
        model.setRemark(form.getRemark());
        logger.info("====处理货品明细...");
        // 监听货品明细变化
        dealProductChange(model, form.getDetails());
        model.setDetails(form.getDetails());
        dealProduct(model);
        logger.info("===保存订单基础数据...");
        if (!this.updateById(model)) {
            throw new Exception("订单保存失败");
        }
        logger.info("===保存货品明细...");
        model.getDetails().forEach(o -> o.setParentId(model.getId()));
        if (!returnOrderProductService.saveOrUpdateBatch(model.getDetails(), 100)) {
            throw new Exception("货品明细保存失败");
        }
        return model;
    }

    @Override
    public void checking(Long orderId, ShiroUser shiroUser) throws Exception {
        ReturnOrderInfo model = this.getById(orderId);
        logger.info("====退货单发货【{}】操作人【{}】===START===", model.getNo(), shiroUser.getLoginNo());
        if (!model.getStatus().equals(SupReturnStatus.WAIT)) {
            throw new Exception("非法操作");
        }
        model.setStatus(SupReturnStatus.DELIVERED);

        logger.info("===更新订单状态...");
        if (!updateById(model)) {
            throw new Exception("订单更新失败");
        }
        logger.info("====退货单发货【{}】操作人【{}】===END===", model.getNo(), shiroUser.getLoginNo());
    }

    @Override
    public void completing(Long orderId, ShiroUser shiroUser) throws Exception {
        ReturnOrderInfo model = this.getById(orderId);
        logger.info("====退货单完成【{}】操作人【{}】===START===", model.getNo(), shiroUser.getLoginNo());
        if (!model.getStatus().equals(SupReturnStatus.DELIVERED)) {
            throw new Exception("非法操作");
        }
        model.setStatus(SupReturnStatus.COMPLETED);

        logger.info("===更新订单状态...");
        if (!updateById(model)) {
            throw new Exception("订单更新失败");
        }
        logger.info("===发送供应商结算通知...");
        kafkaTemplate.send(KafkaTopic.STATISTICS_CAL_SUPPLIER, model.getSupplierId().toString(), TimeUtil.getTime(new Date()));
//        logger.info("===发送货品结算通知...");
//        for(String productId :model.getProductIds().split(",")) {
//            kafkaTemplate.send(KafkaTopic.STATISTICS_CAL_PRODCUT, productId, TimeUtil.getTime(new Date()));
//        }
        logger.info("====退货单发货【{}】操作人【{}】===END===", model.getNo(), shiroUser.getLoginNo());
    }

    @Override
    public void canceling(Long orderId, ShiroUser shiroUser) throws Exception {
        ReturnOrderInfo model = this.getById(orderId);
        logger.info("====退货单撤销【{}】操作人【{}】===START===", model.getNo(), shiroUser.getLoginNo());
        if (!model.getStatus().equals(SupReturnStatus.WAIT)) {
            throw new Exception("非法操作");
        }
        model.setStatus(SupReturnStatus.CANCELED);

        logger.info("===更新订单状态...");
        if (!updateById(model)) {
            throw new Exception("订单更新失败");
        }
        logger.info("====退货单发货【{}】操作人【{}】===END===", model.getNo(), shiroUser.getLoginNo());
    }

    private void dealProduct(ReturnOrderInfo orderInfo) {
        logger.info("===开始处理货品明细");
        // 订单退货量
        BigDecimal quantity = BigDecimal.ZERO;
        // 退货金额
        BigDecimal totalAmount = BigDecimal.ZERO;
        // 打包数
        Integer packages = 0;
        // 货品id链
        List<Long> productIds = new ArrayList<>();
        List<String> productNames = new ArrayList<>();

        // 处理货品明细
        for (ReturnOrderProduct item : orderInfo.getDetails()) {
            // 计算小计
            item.setMoney(item.getQuantity().multiply(item.getPrice()).setScale(2));
            // 计算采购量&结算量
            quantity = quantity.add(item.getQuantity());
            // 计算金额 & 结算金额
            totalAmount = totalAmount.add(item.getMoney());
            productIds.add(item.getProductId());
            productNames.add(item.getName());
            packages += item.getPackages();
        }
        // 更新订单信息
        orderInfo.setQuantity(quantity.setScale(3));
        orderInfo.setTotalAmount(totalAmount.setScale(2));
        orderInfo.setProductIds(StringUtils.join(productIds.toArray(), ","));
        orderInfo.setProductNames(StringUtils.join(productNames.toArray(), ","));
        orderInfo.setPackages(packages);
        logger.info("===退货量【{}】退货总额【{}】货品链【{}】", orderInfo.getQuantity(), orderInfo.getTotalAmount(), orderInfo.getProductIds());
    }

    /**
     * 处理货品变化
     *
     * @param orderInfo 订单
     * @param products  最新明细列表
     */
    private void dealProductChange(ReturnOrderInfo orderInfo, List<ReturnOrderProduct> products) {
        for (ReturnOrderProduct old : orderInfo.getDetails()) {
            // 判断历史明细是否存在  删除
            Stream<ReturnOrderProduct> stream = products.stream().filter(o -> o.getId() != null && o.getId().equals(old.getId()));
            if (stream.count() == 0) {
                returnOrderProductService.removeById(old.getId());
            }
        }
    }
}
